Skip to content

Implement prefetching#9723

Open
gonidelis wants to merge 8 commits into
NVIDIA:mainfrom
gonidelis:prefetch_alt_design
Open

Implement prefetching#9723
gonidelis wants to merge 8 commits into
NVIDIA:mainfrom
gonidelis:prefetch_alt_design

Conversation

@gonidelis

@gonidelis gonidelis commented Jul 7, 2026

Copy link
Copy Markdown
Member

fixes #9588 with a new design.

Adds cub::detail::BlockPrefetch, a standalone block-scope facility for cooperatively emitting global-memory tile-prefetch hints.

Design-only PR: it lands the facility and nothing else, no algorithm is wired to it yet (net diff is a single new header).

What this adds

  • cub::detail::LoadPrefetch - enum of prefetch targets: none, l2 (prefetch.global.L2), l1 (prefetch.global.L1, falls back to L2 where real L1 prefetch is unavailable), and bulk_l2 (TMA cp.async.bulk.prefetch into L2; requires SM90+, no-op on older arch).
  • cub::detail::BlockPrefetch<T, ThreadsPerBlock, Prefetch, PrefetchStride>- a collective with a single static Prefetch(it, items_to_prefetch). The block's threads cooperatively stride the tile, one hint per cache line (or one TMA bulk prefetch for bulk_l2). A no-op for none and for iterators that can't yield a raw address (e.g. CacheModifiedInputIterator), so call sites need no enablement check.

Everything is under detail, no public-API or stability commitment.

@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Progress in CCCL Jul 7, 2026
@gonidelis

Copy link
Copy Markdown
Member Author

See: #3126 (comment) that justifies this PR

@gonidelis gonidelis marked this pull request as ready for review July 8, 2026 07:31
@gonidelis gonidelis requested review from a team as code owners July 8, 2026 07:31
@cccl-authenticator-app cccl-authenticator-app Bot moved this from In Progress to In Review in CCCL Jul 8, 2026
@gonidelis gonidelis requested a review from bernhardmgruber July 8, 2026 07:31
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added device-side cooperative block prefetch hints for tile loads, with selectable targets (none, L2, L1, and bulk L2 on supported hardware) and an optional configurable stride.
    • Prefetching is enabled only for supported contiguous iterators via compile-time checks.
  • Tests

    • Added GPU test coverage validating that prefetch behaves as a no-op for unsupported iterator types and does not affect output correctness across element types, tile shapes, unaligned sub-ranges, and custom strides.

Walkthrough

Adds cub/cub/detail/prefetch.cuh with LoadPrefetch, a capability trait, and BlockPrefetch::Prefetch for cooperative prefetch hints, plus Catch2 coverage for iterator eligibility, alignment, and stride cases.

Changes

Prefetch helper primitives

Layer / File(s) Summary
LoadPrefetch and capability checks
cub/cub/detail/prefetch.cuh
Adds LoadPrefetch values, hosted stringification, and can_prefetch_from for contiguous, address-convertible iterators.
BlockPrefetch implementation and tests
cub/cub/detail/prefetch.cuh, cub/test/catch2_test_block_prefetch.cu
Adds BlockPrefetch::Prefetch, which computes the tile byte span and emits cooperative prefetch.global.L1/L2 or cp.async.bulk.prefetch.L2.global, plus tests for copy preservation, iterator gating, unaligned bases, and custom stride.

Assessment against linked issues

Objective Addressed Explanation
Add cub::detail::BlockPrefetch with none, l1, and l2 modes; dispatch l1 to l2 [#9588] bulk_l2 is added, which is outside the issue’s stated mode set.
Provide a prefetching interface for cooperative block use [#9588]

Out-of-scope changes

Code Change Explanation
Added bulk_l2 enum value and SM_90+ bulk prefetch path (cub/cub/detail/prefetch.cuh) The linked issue only specifies {none, l1, l2} and L1-to-L2 dispatch; this adds an extra mode and PTX path beyond that scope.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 54e03265-c405-4ed7-9a6a-2dda8d2ab5e1

📥 Commits

Reviewing files that changed from the base of the PR and between 48ff8d1 and 010f57a.

📒 Files selected for processing (6)
  • cub/benchmarks/bench/reduce/by_key.cu
  • cub/cub/agent/agent_reduce_by_key.cuh
  • cub/cub/detail/prefetch.cuh
  • cub/cub/device/dispatch/dispatch_reduce_by_key.cuh
  • cub/cub/device/dispatch/tuning/tuning_reduce_by_key.cuh
  • cub/test/catch2_test_device_reduce_by_key_env.cu

Comment thread cub/cub/agent/agent_reduce_by_key.cuh Outdated
@github-actions

This comment has been minimized.

@gonidelis gonidelis force-pushed the prefetch_alt_design branch from 010f57a to 6c6b182 Compare July 8, 2026 23:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b9f60ed6-bca2-4a64-8026-af6c18a4821f

📥 Commits

Reviewing files that changed from the base of the PR and between 010f57a and 6c6b182.

📒 Files selected for processing (1)
  • cub/cub/detail/prefetch.cuh

Comment thread cub/cub/detail/prefetch.cuh Outdated
@gonidelis gonidelis force-pushed the prefetch_alt_design branch from 233e4e5 to e299245 Compare July 9, 2026 00:00
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

😬 CI Workflow Results

🟥 Finished in 1h 18m: Pass: 84%/287 | Total: 1d 20h | Max: 1h 00m | Hits: 96%/204333

See results here.

Comment thread cub/cub/detail/prefetch.cuh Outdated
Comment thread cub/cub/detail/prefetch.cuh Outdated
Comment thread cub/cub/detail/prefetch.cuh Outdated
Comment thread cub/cub/detail/prefetch.cuh Outdated
Comment thread cub/cub/detail/prefetch.cuh Outdated
Comment thread cub/cub/detail/prefetch.cuh Outdated
static_assert(sizeof(cub::detail::it_value_t<RandomAccessIterator>) == sizeof(T),
"BlockPrefetch element type T must match the iterator's value type size");
const int linear_tid = static_cast<int>(threadIdx.x);
const unsigned int total_bytes = static_cast<unsigned int>(items_to_prefetch) * unsigned{sizeof(T)};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: we want to prefetch the entire tile not just the data of the first thread:

Suggested change
const unsigned int total_bytes = static_cast<unsigned int>(items_to_prefetch) * unsigned{sizeof(T)};
const unsigned int total_bytes = static_cast<unsigned int>(items_to_prefetch) * unsigned{sizeof(T)} * ThreadsPerBlock;

@gonidelis gonidelis Jul 9, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will reject this as we want to express full set of elements to prefetch for edge cases / ragged loads. I will go with the renames you suggested above though.

if i were to apply this suggested fix the Prefetch() call would be problematic:

// full tile: pass items per thread
BlockPrefetch<128, l2>::Prefetch(d_keys_in + tile_offset, 11);      // 11 × 128 = 1408 ok

// ragged last tile, 500 items left:
BlockPrefetch<128, l2>::Prefetch(d_keys_in + tile_offset, 4);       // 4 * 128 = 512 --> 12 past the end
BlockPrefetch<128, l2>::Prefetch(d_keys_in + tile_offset, 3);       // 3 * 128 = 384 --> misses 116
// no integer means "500"

Comment thread cub/test/catch2_test_block_prefetch.cu Outdated
Comment thread cub/test/catch2_test_block_prefetch.cu
Comment thread cub/test/catch2_test_block_prefetch.cu Outdated
Comment thread cub/test/catch2_test_block_prefetch.cu Outdated
gonidelis added 3 commits July 9, 2026 11:28
…tor params

- Use Apache-2.0 WITH LLVM-exception on both new files (BSD-3-Clause is the
  legacy license; all recently added CUB files use Apache-2.0)
- Drop BlockPrefetch's T template parameter and the static_assert that policed
  it; the element size is derived from the iterator's value type instead
- Rename iterator template parameters to It: can_prefetch_from accepts any
  iterator category and tests for contiguous, so RandomAccessIterator was
  misleading
gonidelis added 2 commits July 9, 2026 12:17
- Cover the iterators users actually pass: thrust::device_vector and
  thrust::universal_vector (rejected by can_prefetch_from, safe no-op) and
  cuda::buffer's heterogeneous_iterator (contiguous, accepted), per review
- Use thrust::no_init for all vectors whose contents get overwritten
- Use signed byte/offset math; a non-positive count now trivially no-ops
@gonidelis gonidelis requested a review from bernhardmgruber July 9, 2026 19:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cub/cub/detail/prefetch.cuh (1)

133-135: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

important: keep l1 mapped to L2 until native L1 support is gated.

The PR contract says l1 falls back to L2 on current unsupported architectures, but this branch always emits prefetch.global.L1. Until there is an architecture-gated native path, emit L2 here.

           if constexpr (PrefetchLevel == LoadPrefetch::l1)
           {
-            asm volatile("prefetch.global.L1 [%0];" : : "l"(::cuda::ptx::__as_ptr_gmem(src_ptr + offset)) : "memory");
+            asm volatile("prefetch.global.L2 [%0];" : : "l"(::cuda::ptx::__as_ptr_gmem(src_ptr + offset)) : "memory");
           }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4a3923e5-b623-4845-80b7-4ab8e42f07db

📥 Commits

Reviewing files that changed from the base of the PR and between e299245 and 6f53c04.

📒 Files selected for processing (2)
  • cub/cub/detail/prefetch.cuh
  • cub/test/catch2_test_block_prefetch.cu

//! @tparam ThreadsPerBlock Number of threads in the block cooperating on the hints.
//! @tparam PrefetchLevel Which cache level to target (see ``LoadPrefetch``); ``none`` makes ``Prefetch()`` a no-op.
//! @tparam PrefetchStride Byte stride between successive hints; one hint per cache line (default 128 B).
template <int ThreadsPerBlock, LoadPrefetch PrefetchLevel = LoadPrefetch::l2, int PrefetchStride = 128>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

important: reject non-positive block/stride configurations.

PrefetchStride <= 0 or ThreadsPerBlock <= 0 makes the loop on Line 130 stop progressing or address backwards. Add compile-time guards on the template.

 template <int ThreadsPerBlock, LoadPrefetch PrefetchLevel = LoadPrefetch::l2, int PrefetchStride = 128>
 struct BlockPrefetch
 {
+  static_assert(ThreadsPerBlock > 0, "ThreadsPerBlock must be positive");
+  static_assert(PrefetchStride > 0, "PrefetchStride must be positive");
+

As per path instructions, focus on algorithm correctness, memory access safety, and CUDA synchronization/performance risks.

Also applies to: 130-130

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

Add cub::detail::BlockPrefetch

2 participants